﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;
using System.ComponentModel;
using Atosenet.PluginEngine;

namespace Atosenet.IO
{
    [PluginAttribute("Atosenet", "Atosenet.IO.ComIO", "串口连接", PluginType.IO)]
    internal class ComIO : BaseIO
    {
        #region 成员

        private SerialPort _seriaPort = new SerialPort();

        #endregion


        #region 初始化

        public ComIO()
            : base(ComIOParameter.Default)
        { }

        public ComIO(ComIOParameter param)
            : base(param)
        { }

        protected override bool Initialize()
        {
            _seriaPort.DataReceived -= ComPort_DataReceived;
            _seriaPort.DataReceived += new SerialDataReceivedEventHandler(ComPort_DataReceived);
            _seriaPort.ErrorReceived -= ComPort_ErrorReceived;
            _seriaPort.ErrorReceived += new SerialErrorReceivedEventHandler(ComPort_ErrorReceived);
            return base.Initialize() && ComIOParameter.IsPortAvailable(IOParam.PortName);
        }

        #endregion


        #region 公开函数

        public override bool ApplyParameter()
        {
            try
            {
                if (IsOpened)
                    return false;

                _seriaPort.PortName = IOParam.PortName;
                _seriaPort.BaudRate = (int)IOParam.BaudRate;
                _seriaPort.Parity = IOParam.PortParity;
                _seriaPort.Handshake = IOParam.FlowControl;
                _seriaPort.DataBits = IOParam.DataBits;
                _seriaPort.StopBits = IOParam.StopBits;
                _seriaPort.ReadTimeout = IOParam.ReadTimeout;
                _seriaPort.WriteTimeout = IOParam.WriteTimeout;
                return true;
            }
            catch
            {
                return false;
            }
        }

        public override bool Open()
        {
            try
            {
                if (_seriaPort.IsOpen || IsOpened)
                    return false;

                _seriaPort.Open();
                OnIOOpened();
                return true;
            }
            catch
            {
                return false;
            }
        }

        public override bool Close()
        {
            try
            {
                if (!_seriaPort.IsOpen || !IsOpened)
                    return false;

                _seriaPort.Close();
                OnIOClosed();
                return true;
            }
            catch
            {
                return false;
            }
        }

        public override bool Close(int id)
        {
            if (id == ID)
                return Close();

            return false;
        }

        public override int WriteTo(int id, byte[] buffer, int offset, int length)
        {
            if (id == ID)
                return Write(buffer, offset, length);

            return -1;
        }

        public override int Write(byte[] buffer, int offset, int length)
        {
            try
            {
                this._seriaPort.Write(buffer, offset, length);
                return length;
            }
            catch
            {
                OnRawDataReceived(IOErrorType.WriteError);
                return -1;
            }
        }

        #endregion


        #region 静态对象
                
        public static ComIO CreateInstance(ComIOParameter param)
        {
            ComIO io = new ComIO(param);
            return io;
        }

        public static ComIO CreateInstance()
        {
            ComIO io = new ComIO();
            return io;
        }

        #endregion


        #region 核心函数

        private void ComPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int nCount = _seriaPort.BytesToRead;

            if (nCount > 0)
            {
                byte[] data = new byte[nCount];
                _seriaPort.Read(data, 0, nCount);
                OnRawDataReceived(data);
            }
        }

        private void ComPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
        {
            OnRawDataReceived(IOErrorType.ReadError);
        }

        #endregion


        #region 属性

        public new ComIOParameter IOParam
        {
            get { return base.IOParam as ComIOParameter; } 
        }

        #endregion
    }
}
